import unittest
import copy
from ConfigChecker import *

class ConfigCheckerTest(unittest.TestCase):
    def test_global(self):
        # 无gloabl时填入默认的
        conf = {OPT_PROJECTS:{'main':{OPT_TYPE:'exe'}}}
        conf, msg = checkConf(conf, '.')
        self.assertEqual(msg, '')
        self.assertEqual(DEFAULT_GLOBAL, conf[OPT_GLOBAL])
        # 有global但是不完整时，补充没有的字段
        conf = {OPT_GLOBAL:{OPT_BUILD_OPTIONS:{OPT_CXX_STANDARD:'c++98'}}, OPT_PROJECTS:{'main':{OPT_TYPE:'exe'}}}
        conf, msg = checkConf(conf, '.')
        self.assertEqual(conf[OPT_GLOBAL][OPT_BUILD_OPTIONS][OPT_CXX_STANDARD], 'c++98')
        conf[OPT_GLOBAL][OPT_BUILD_OPTIONS][OPT_CXX_STANDARD] = DEFAULT_CXX_STANDARD
        self.assertEqual(DEFAULT_GLOBAL, conf[OPT_GLOBAL])
        self.assertEqual(msg, '')
        # 有global且完整时，不做修改
        conf = {OPT_GLOBAL:copy.deepcopy(DEFAULT_GLOBAL), OPT_PROJECTS:{'main':{OPT_TYPE:'exe'}}}
        conf[OPT_GLOBAL][OPT_BUILD_OPTIONS][OPT_C_STANDARD] = 'c999'
        conf[OPT_GLOBAL][OPT_BUILD_OPTIONS][OPT_OPT_LEVEL] = 'O2'
        g = copy.deepcopy(conf[OPT_GLOBAL])
        conf, msg = checkConf(conf, '.')
        self.assertEqual(g, conf[OPT_GLOBAL])
        self.assertEqual(msg, '')

    def test_proj(self):
        conf = {}
        conf, msg = checkConf(conf, '.')
        self.assertEqual(conf, None)
        self.assertEqual(msg, '"projects" is missing.')
        # 项目名是否合法
        conf = {OPT_PROJECTS:{'0main':{OPT_TYPE:'exe'}}}
        conf, msg = checkConf(conf, '.')
        self.assertEqual(conf, None)
        self.assertEqual(msg, 'project name "0main" is illegal.  location: ["projects"]')
        conf = {OPT_PROJECTS:{123:{OPT_TYPE: 'dll'}}}
        conf, msg = checkConf(conf, '.')
        self.assertEqual(conf, None)
        self.assertEqual(msg, 'project name "123" should be string.  location: ["projects"]')
        # global构建选项覆盖项目中没有设置的构建选项
        conf = { \
            OPT_GLOBAL:{OPT_BUILD_OPTIONS:{OPT_CXX_STANDARD:'c++2333'}}, \
            OPT_PROJECTS:{'main':{OPT_TYPE:'exe', OPT_BUILD_OPTIONS:{OPT_C_STANDARD: 'c2333'}}}}
        conf, msg = checkConf(conf, '.')
        self.assertEqual(msg, '')
        self.assertEqual('c2333', conf[OPT_PROJECTS]['main'][OPT_BUILD_OPTIONS][OPT_C_STANDARD])
        conf[OPT_PROJECTS]['main'][OPT_BUILD_OPTIONS][OPT_C_STANDARD] = conf[OPT_GLOBAL][OPT_BUILD_OPTIONS][OPT_C_STANDARD]
        self.assertEqual(conf[OPT_GLOBAL][OPT_BUILD_OPTIONS], conf[OPT_PROJECTS]['main'][OPT_BUILD_OPTIONS])
        self.assertEqual('c++2333', conf[OPT_GLOBAL][OPT_BUILD_OPTIONS][OPT_CXX_STANDARD])
        conf[OPT_GLOBAL][OPT_BUILD_OPTIONS][OPT_CXX_STANDARD] = DEFAULT_CXX_STANDARD
        self.assertEqual(DEFAULT_BUILD_OPTIONS, conf[OPT_GLOBAL][OPT_BUILD_OPTIONS])
        # 依赖的项目不存在
        conf = {OPT_PROJECTS:{'main':{OPT_TYPE:'exe', OPT_DEPENDENCY:['aaa']}, 'aa':{OPT_TYPE: 'lib'}}}
        conf, msg = checkConf(conf, '.')
        self.assertEqual(conf, None)
        self.assertEqual(msg, 'dependency project name "aaa" not exist.')
        # 产出类型不对
        conf = {OPT_PROJECTS:{'main':{OPT_TYPE:'mexe2333'}}}
        conf, msg = checkConf(conf, '.')
        self.assertEqual(conf, None)
        self.assertEqual(msg, 'project type "mexe2333" is illegal.  location: ["projects"]["main"]')

    def test_type_error(self):
        # checkIfExist检查类形
        conf = {OPT_PROJECTS:{'main':{OPT_TYPE:123}}}
        conf, msg = checkConf(conf, '.'); self.assertEqual(conf, None)
        self.assertEqual(msg, 'value type of "%s" should be "<class \'str\'>".  location: ["%s"]["main"]["%s"]'%(OPT_TYPE, OPT_PROJECTS, OPT_TYPE))
        # setIfExist检查类形
        conf = {OPT_PROJECTS:{'main':{OPT_TYPE:"lib", OPT_DEPENDENCY:'asdf'}}}
        conf, msg = checkConf(conf, '.'); self.assertEqual(conf, None)
        self.assertEqual(msg, 'value type of "%s" should be "<class \'list\'>".  location: ["%s"]["main"]["%s"]'%(OPT_DEPENDENCY, OPT_PROJECTS, OPT_DEPENDENCY))
        conf = {OPT_PROJECTS:{123:{OPT_TYPE:"exe"}}}
        
    def test_unsupport_options(self):
        pass
    
class BuilderTest(unittest.TestCase):
    def test_incdirs(self):
        pass

    def test_compile_flags(self):
        pass

if __name__ == '__main__':
    unittest.main()
